package labox.innovation.gameserver.model;

import java.util.Collection;
import java.util.Map;

import javolution.util.FastMap;
import labox.innovation.gameserver.ai.CtrlIntention;
import labox.innovation.gameserver.model.actor.L2Attackable;
import labox.innovation.gameserver.model.actor.L2Playable;

/**
 * This class ...
 * 
 * @version $Revision: 1.3.4.4 $ $Date: 2005/03/27 15:29:33 $
 */
public final class SceneRegion {

	/**
	 *此区域内所有可玩的对象（包括玩家和召唤类）
	 */
	private Map<Long, L2Playable> _allPlayable;

	/**
	 * 此区域内所有的可见对象
	 */
	private Map<Long, L2Object> _visibleObjects;

	private int _tilex, _tiley, _x, _y, _width, _height;

	private Scene _scene;

	/**
	 * 当前区域是否激活
	 */
	private boolean _active;

	public SceneRegion(int tilex, int tiley, Scene world) {
		_tilex = tilex;
		_tiley = tiley;
		_scene = world;
		_x = tilex << Scene.SHIFT_BY;
		_y = tiley << Scene.SHIFT_BY;
		_width = _x + Scene.TILEWH > world.getWidth() ? world.getWidth() - _x : Scene.TILEWH;
		_height = _y + Scene.TILEWH > world.getHeight() ? world.getHeight() - _y : Scene.TILEWH;
		_allPlayable = new FastMap<Long, L2Playable>();
		_visibleObjects = new FastMap<Long, L2Object>();
	}

	/**
	 * 向此区域内添加一个对象
	 */
	public void addVisibleObject(L2Object object) {
		if (object == null)
			return;
		_visibleObjects.put(object.getObjectId(), object);
		if (object instanceof L2Playable) {
			_allPlayable.put(object.getObjectId(), (L2Playable) object);
			if (_allPlayable.size() == 1)
				neighborsTask(true);//激活此区域及周围8格内的NPC角色的AI
		}
	}

	/**
	 * 从此区域内删除一个对象
	 * 
	 * @param object
	 */
	public void removeVisibleObject(L2Object object) {
		if (object == null)
			return;
		_visibleObjects.remove(object.getObjectId());
		if (object instanceof L2Playable) {
			_allPlayable.remove(object.getObjectId());
			if (_allPlayable.isEmpty())//如果没有任何角色了关闭所有的NPC角色AI
				neighborsTask(false);
		}
	}

	public Map<Long, L2Playable> getVisiblePlayable() {
		return _allPlayable;
	}

	public Map<Long, L2Object> getVisibleObjects() {
		return _visibleObjects;
	}

	public String getName() {
		return "Scene:" + _scene + "(" + _x + ", " + _y + "," + _width + "," + _height + ")";
	}

	public int get_tilex() {
		return _tilex;
	}

	public int get_tiley() {
		return _tiley;
	}

	/**
	 * 此区域是否激活
	 * 
	 * @return
	 */
	public Boolean isActive() {
		return _active;
	}

	public Scene getScene() {
		return _scene;
	}

	/**
	 * 设置是否激活此区域，开启或关闭此区域的所有有攻击特性的对象AI
	 * 
	 * @param value
	 */
	private void setActive(boolean value) {
		if (_active == value)
			return;
		_active = value;
		switchAI(value);//切换AI
	}

	/**
	 * 打开或关闭区域内所有具有攻击行为的对象的AI
	 * 
	 * @param on
	 */
	private void switchAI(Boolean on) {
		if (on) {
			Collection<L2Object> _obj = _visibleObjects.values();
			for (L2Object o : _obj) {
				if (o instanceof L2Attackable) {
					L2Attackable mob = (L2Attackable) o;
					mob.disableCoreAI(false);
					mob.getStatus().startRegeneration();
				}
			}
		} else {
			Collection<L2Object> _obj = _visibleObjects.values();
			L2Attackable mob;
			for (L2Object o : _obj) {
				if (o instanceof L2Attackable) {
					mob = (L2Attackable) o;
					mob.disableCoreAI(true);
					//设置目标为null，取消攻击或施法
					mob.setTarget(null);
					//停止这个对象身上正在处理的所有效果（buff和debuff）
					mob.stopAllEffects();
					//清空仇恨列表
					mob.clearAggroList();
					//设置AI空闲
					mob.getAI().setIntention(CtrlIntention.AI_INTENTION_IDLE);
					mob.getStatus().stopRegeneration();
				}
			}
		}

	}

	public Boolean areNeighborsEmpty() {
		// 包括自己在内的所有周边的region是否已经没有玩家
		SceneRegion sr;
		for (int i = -1; i <= 1; i++) {
			for (int j = -1; j <= 1; j++) {
				sr = _scene.getRegion(_tilex + i, _tiley + j);
				if (sr == null)
					continue;
				if (sr.isActive() && !sr._allPlayable.isEmpty())
					return false;
			}
		}
		return true;
	}

	public void neighborsTask(boolean _isActivating) {
		SceneRegion sr;
		if (_isActivating) {
			// for each neighbor, if it's not active, activate.
			for (int i = -1; i <= 1; i++) {
				for (int j = -1; j <= 1; j++) {
					sr = _scene.getRegion(_tilex + i, _tiley + j);
					if (sr == null)
						continue;
					sr.setActive(true);
				}
			}
		} else {
			if (areNeighborsEmpty())
				setActive(false);
			for (int i = -1; i <= 1; i++) {
				for (int j = -1; j <= 1; j++) {
					sr = _scene.getRegion(_tilex + i, _tiley + j);
					if (sr == null)
						continue;
					if (sr.areNeighborsEmpty())
						sr.setActive(false);
				}
			}
		}
	}

}
